package by.yakusekmaxim.bookgid.services.impl;

import java.util.List;

import javax.inject.Inject;
import javax.persistence.metamodel.SingularAttribute;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import by.yakusekmaxim.bookgid.dataaccess.BookDao;
import by.yakusekmaxim.bookgid.dataaccess.util.Filter;
import by.yakusekmaxim.bookgid.datamodel.Book;
import by.yakusekmaxim.bookgid.datamodel.UserAccount;
import by.yakusekmaxim.bookgid.datamodel.enums.PublicationStatus;
import by.yakusekmaxim.bookgid.datamodel.enums.UserRole;
import by.yakusekmaxim.bookgid.services.BookService;
import by.yakusekmaxim.bookgid.services.util.CrudMessage;
import by.yakusekmaxim.bookgid.services.util.enums.Message;
import by.yakusekmaxim.bookgid.services.util.enums.TypeMessage;

@Service
public class BookServiceImpl implements BookService {
	private static final Logger LOGGER = LoggerFactory
			.getLogger(BookServiceImpl.class);

	@Inject
	private BookDao dao;

	@Override
	public Book get(Long id) {
		Book entity = dao.getById(id);
		return entity;
	}

	@Override
	public void delete(Book book) {
		LOGGER.debug("Remove: {}", book);
		dao.delete(book.getId());

	}

	@Override
	public void deleteAll() {
		LOGGER.debug("Remove all images");
		dao.deleteAll();
	}

	
	@Override
	public void saveOrUpdate(Book book) {
		if (book.getId() == null) {
			LOGGER.debug("Save new: {}", book);
			dao.insert(book);
		} else {
			LOGGER.debug("Update: {}", book);
			dao.update(book);
		}
	}
	
	@Override
	public CrudMessage saveOrUpdate(Book book, UserAccount user) {
		CrudMessage crudMessage = new CrudMessage();
		if (user == null) {
			crudMessage.setTypeMessage(TypeMessage.typemessage_error);
			crudMessage.setMessage(Message.message_are_not_allowed);
			return crudMessage;
		} else if (user.getRole() == UserRole.userrole_user) {
			crudMessage.setTypeMessage(TypeMessage.typemessage_error);
			crudMessage.setMessage(Message.message_are_not_allowed);
			return crudMessage;
		} else if (user.getRole() == UserRole.userrole_editor) {
			// Проверка на ноличие в базе по book.id:
			// Если есть
			if (checkForBd(book)) {
				Book bookFromDb = get(book.getId());

				// Если Book.status в базе данных:
				if (bookFromDb.getStatus() == PublicationStatus.publicationstatus_edited) {
					if (book.getName() != null) {
						LOGGER.debug("Update: {}", book);
						dao.update(book);
						crudMessage
								.setTypeMessage(TypeMessage.typemessage_information);
						crudMessage.setMessage(Message.message_update);
						return crudMessage;
					} else {
						LOGGER.debug("The {} should contain the name", book);
						crudMessage
								.setTypeMessage(TypeMessage.typemessage_error);
						crudMessage
								.setMessage(Message.message_fields_must_not_be_empty);
						return crudMessage;
					}

				} else if (bookFromDb.getStatus() == PublicationStatus.publicationstatus_validation) {
					if (сheckForNullValues(book)) {
						LOGGER.debug("Update: {}", book);
						dao.update(book);
						crudMessage
								.setTypeMessage(TypeMessage.typemessage_information);
						crudMessage.setMessage(Message.message_update);
						return crudMessage;
					} else {
						LOGGER.debug(
								"The {} should contain the genre, alias, name, date, description, image",
								book);
						crudMessage
								.setTypeMessage(TypeMessage.typemessage_error);
						crudMessage
								.setMessage(Message.message_fields_must_not_be_empty);
						return crudMessage;
					}

				} else {
					LOGGER.debug(
							"Insufficient privileges ie {} to perform the operation",
							user);
					crudMessage.setTypeMessage(TypeMessage.typemessage_error);
					crudMessage.setMessage(Message.message_are_not_allowed);
					return crudMessage;
				}
				// Проверка на ноличие в базе по book.id:
				// Если нету
			} else {
				if (book.getStatus() == PublicationStatus.publicationstatus_edited) {
					if (book.getName() != null) {
						LOGGER.debug("Save new: {}", book);
						dao.insert(book);
						crudMessage
								.setTypeMessage(TypeMessage.typemessage_information);
						crudMessage.setMessage(Message.message_create);
						return crudMessage;
					} else {
						LOGGER.debug("The {} should contain the name", book);
						crudMessage
								.setTypeMessage(TypeMessage.typemessage_error);
						crudMessage.setMessage(Message.message_are_not_allowed);
						return crudMessage;
					}

				} else if (book.getStatus() == PublicationStatus.publicationstatus_validation) {
					if (сheckForNullValues(book)) {
						LOGGER.debug("Save new: {}", book);
						dao.insert(book);
						crudMessage
								.setTypeMessage(TypeMessage.typemessage_information);
						crudMessage.setMessage(Message.message_create);
						return crudMessage;
					} else {
						LOGGER.debug(
								"The {} should contain the genre, alias, name, date, description, image",
								book);
						crudMessage
								.setTypeMessage(TypeMessage.typemessage_error);
						crudMessage
								.setMessage(Message.message_fields_must_not_be_empty);
						return crudMessage;
					}

				} else {
					LOGGER.debug(
							"Insufficient privileges ie {} to perform the operation! Forced value Book.status = publicationstatus_validation ",
							user);
					book.setStatus(PublicationStatus.publicationstatus_validation);
					if (сheckForNullValues(book)) {
						LOGGER.debug("Save new: {}", book);
						dao.insert(book);
						crudMessage
								.setTypeMessage(TypeMessage.typemessage_notification);
						crudMessage.setMessage(Message.message_create);
						return crudMessage;
					} else {
						LOGGER.debug(
								"The {} should contain the genre, alias, name, date, description, image",
								book);
						crudMessage
								.setTypeMessage(TypeMessage.typemessage_error);
						crudMessage
								.setMessage(Message.message_fields_must_not_be_empty);
						return crudMessage;
					}
				}
			}
		} else if (user.getRole() == UserRole.userrole_admin) {
			Book bookFromDb = get(book.getId());
			if (bookFromDb.getStatus() == PublicationStatus.publicationstatus_edited) {
				if (book.getName() != null) {
					LOGGER.debug("Update: {}", book);
					dao.update(book);
					crudMessage
							.setTypeMessage(TypeMessage.typemessage_information);
					crudMessage.setMessage(Message.message_update);
					return crudMessage;
				} else {
					LOGGER.debug("The {} should contain the name", book);
					crudMessage.setTypeMessage(TypeMessage.typemessage_error);
					crudMessage
							.setMessage(Message.message_fields_must_not_be_empty);
					return crudMessage;
				}

			} else {
				if (сheckForNullValues(book)) {
					LOGGER.debug("Update: {}", book);
					dao.update(book);
					crudMessage
							.setTypeMessage(TypeMessage.typemessage_information);
					crudMessage.setMessage(Message.message_update);
					return crudMessage;
				} else {
					LOGGER.debug(
							"The {} should contain the genre, alias, name, date, description, image",
							book);
					crudMessage.setTypeMessage(TypeMessage.typemessage_error);
					crudMessage
							.setMessage(Message.message_fields_must_not_be_empty);
					return crudMessage;
				}
			}
		}
		return null;

	}



	private boolean checkForBd(Book book) {
		if (book.getId() == null) {
			LOGGER.debug("The {} is not in the database", book);
			return false;
		} else {
			LOGGER.debug("There is a {} in the database", book);
			return true;
		}
	}

	private boolean сheckForNullValues(Book book) {
		if (book.getName() != null & book.getGenre() != null
				& book.getAuthor() != null & book.getDate() != null
				& book.getDescription() != null & book.getImage() != null) {
			return true;
		} else {
			return false;
		}
	}

	@Override
	public CrudMessage delete(Book book, UserAccount user) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Long getCount() {
		return dao.getCount();
	}

	@Override
	public Long getCount(SingularAttribute<Book, ?> attribute, Object value) {
		return dao.getCount(attribute, value);
	}

	@Override
	public List<Book> getAllBook(SingularAttribute<Book, ?> attr,
			boolean ascending, int startRecord, int pageSize) {
		return dao.getAllBook(attr, ascending, startRecord, pageSize);
	}

	@Override
	public List<Book> getAllBook(SingularAttribute<Book, ?> attr,
			boolean ascending, int startRecord, int pageSize,
			Filter<Book> filter) {
		return dao.getAllBook(attr, ascending, startRecord, pageSize,filter);
	}

	@Override
	public List<Book> getAllPublicBook(SingularAttribute<Book, ?> attr,
			boolean ascending, int startRecord, int pageSize) {
		return dao.getAllPublicBook(attr, ascending, startRecord, pageSize);
	}

	@Override
	public List<Book> getAllPublicBook(SingularAttribute<Book, ?> attr,
			boolean ascending, int startRecord, int pageSize,
			Filter<Book> filter) {
		return dao.getAllPublicBook(attr, ascending, startRecord, pageSize,filter);
	}

}
